#ifndef _IM_SERVER_GROUP_ADAPTER_
#define _IM_SERVER_GROUP_ADAPTER_

#include "GroupService.h"

#include "im/common/common.h"
#include "melon/client/thrift_client_pool.h"
#include "melon/client/zk_service_locator.h"
#include "base/singleton.h"

namespace imserver {

#define GROUP_SERVER_KEY "/im/group_service/v1/shard_0"

using melon::client::ClientPool;

class GroupAdapter : public base::Singleton<GroupAdapter> {
public:

  int GetGroupInfo(GroupInfo& _return, int64_t group_id, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      GroupServiceClient * client = pool_.Alloc(GROUP_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("GroupAdapter::GetGroupInfo --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->GetGroupInfo(_return, group_id);
      } catch (const std::exception & e) {
        LOG_ERROR("GroupAdapter::GetGroupInfo --> err. error:" << e.what() << " retry:" << i);
        success = false;
      }
      pool_.Release(GROUP_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

  int GetGroupInfoByEntityId(GroupInfo& _return, int32_t type, int64_t entity_id, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      GroupServiceClient * client = pool_.Alloc(GROUP_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("GroupAdapter::GetGroupInfoByEntityId --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->GetGroupInfoByEntityId(_return, type, entity_id);
      } catch (const std::exception & e) {
        LOG_ERROR("GroupAdapter::GetGroupInfoByEntityId --> err. error:" << e.what() << " retry:" << i);
        success = false;
      }
      pool_.Release(GROUP_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

  int GetGroupMemberIds(std::set<int64_t>& _return, int64_t group_id, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      GroupServiceClient * client = pool_.Alloc(GROUP_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("GroupAdapter::GetGroupMemberIds --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->GetGroupMemberIds(_return, group_id);
      } catch (const std::exception & e) {
        LOG_ERROR("GroupAdapter::GetGroupMemberIds --> err. error:" << e.what() << " retry:" << i);
        success = false;
      }
      pool_.Release(GROUP_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

  int GetJoinedGroupIds(std::set<int64_t>& _return, int64_t uid, int max_retry = 1) {
    for(int i = 0; i < max_retry; ++i) {
      GroupServiceClient * client = pool_.Alloc(GROUP_SERVER_KEY);
      if (client == NULL) {
        LOG_ERROR("GroupAdapter::GetJoinedGroupIds --> connect err.");
        return -1;
      }

      bool success = true;
      try {
        client->GetJoinedGroupIds(_return, uid);
      } catch (const std::exception & e) {
        LOG_ERROR("GroupAdapter::GetJoinedGroupIds --> err. error:" << e.what() << " retry:" << i);
        success = false;
      }
      pool_.Release(GROUP_SERVER_KEY, client, success);
      if (success) {
        return 0;
      }
    }
    return -2;
  }

private:
  friend class base::Singleton<GroupAdapter>;

  GroupAdapter() : pool_(300) {
    ConfigReader cfg("../conf/rpc_adapters.conf");
    std::string default_location(cfg.Get("group_service", "service_list"));
    pool_.set_default_location(default_location);

    ConfigReader zk_cfg("../conf/zookeeper.conf");
    if (!zk_cfg) {
      LOG_WARN("Config file ../conf/zookeeper.conf read error!");
      return;
    }
    pool_.set_locator(new melon::client::ZkServiceLocator(zk_cfg.Get("zookeeper", "service_registry").c_str()));
  }


  ClientPool<GroupServiceClient> pool_;
};

}

#endif // _IM_SERVER_GROUP_ADAPTER_
